package com.jsmile.cloud.msgcenter.pay;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.egzosn.pay.common.bean.RefundResult;
import com.jsmile.cloud.msgcenter.api.exception.MsgException;
import com.jsmile.cloud.msgcenter.api.req.ReqPayOrderCreate;
import com.jsmile.cloud.msgcenter.api.req.ReqPayOrderRefund;
import com.jsmile.cloud.msgcenter.api.req.ReqPayOrderSuccess;
import com.jsmile.cloud.msgcenter.pay.model.PayInfo;
import com.jsmile.cloud.msgcenter.pay.model.PayOrderInfo;
import com.jsmile.cloud.msgcenter.pay.model.RefundOrderInfo;
import com.jsmile.cloud.msgcenter.pay.repo.PayInfoSearchRepository;
import com.jsmile.cloud.msgcenter.pay.repo.PayOrderRepository;
import com.jsmile.cloud.msgcenter.pay.repo.PayOrderSearchRepository;
import com.jsmile.cloud.msgcenter.pay.repo.RefundOrderRepository;
import com.jsmile.cloud.msgcenter.zf.strategy.factory.PayStrategyFactory;
import com.jsmile.cloud.tradecenter.api.req.ReqPayOrder;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@AllArgsConstructor
public class PayOrderApplicationService {

    private final PayOrderRepository payOrderRepository;
    private final PayOrderSearchRepository payOrderSearchRepository;
    private final PayInfoSearchRepository payInfoSearchRepository;
    private final PayStrategyFactory payStrategyFactory;
    private final RefundOrderRepository refundOrderRepository;

    public void create(ReqPayOrderCreate reqPayOrderCreate) {
        PayInfo payInfo = payInfoSearchRepository.findByPayType(reqPayOrderCreate.getCurTenantId(), reqPayOrderCreate.getPayType());
        List<PayOrderInfo> payOrders = PayOrderInfo.create(reqPayOrderCreate, payInfo);
        payOrderRepository.saveBatch(payOrders);
    }

    public void paySuccess(ReqPayOrderSuccess reqPayOrderSuccess) {
        List<PayOrderInfo> payOrders = payOrderSearchRepository.findByOutTradeNo(reqPayOrderSuccess.getOutTradeNo());
        PayOrderInfo.paySuccess(reqPayOrderSuccess, payOrders);
        payOrderRepository.updateBatchById(payOrders);
    }

    public void refund(ReqPayOrderRefund reqPayOrderRefund) {
        PayOrderInfo payOrder = payOrderSearchRepository.findByOrderNo(reqPayOrderRefund.getOrderNo());
        List<PayOrderInfo> payOrderList = payOrderSearchRepository.findByOutTradeNo(payOrder.getOutTradeNo());
        RefundOrderInfo refundOrderInfo = RefundOrderInfo.create(payOrder, reqPayOrderRefund.getRefundAmount(), payOrderList.stream().mapToLong(PayOrderInfo::getPayAmount).sum());
        RefundResult refundResult = payStrategyFactory.findStrategy(payOrder.getPayType()).refund(refundOrderInfo);
        if (!StringUtils.equals(refundResult.getCode(), "10000")) {
            throw new MsgException(refundResult.getMsg());
        }
        refundOrderRepository.save(refundOrderInfo);
    }

    public Map pay(ReqPayOrder reqPayOrder) {
        List<PayOrderInfo> payOrders = payOrderSearchRepository.findByOrderNos(reqPayOrder.getOrderNos());
        PayOrderInfo.pay(reqPayOrder, payOrders);
        // 实际支付
        Map map = payStrategyFactory.findStrategy(reqPayOrder.getPayType()).pay(payOrders);
        log.info("第三方支付返回信息:{}", JSON.toJSONString(map));

        payOrderRepository.updateBatchById(payOrders);
        return map;
    }

    // 不经过订单的支付
    public Map pay(ReqPayOrderCreate reqPayOrderCreate) {
        PayInfo payInfo = payInfoSearchRepository.findByPayType(reqPayOrderCreate.getCurTenantId(), reqPayOrderCreate.getPayType());
        List<PayOrderInfo> payOrders = PayOrderInfo.create(reqPayOrderCreate, payInfo);
        payOrderRepository.saveBatch(payOrders);
        // 实际支付
        Map map = payStrategyFactory.findStrategy(reqPayOrderCreate.getPayType()).pay(payOrders);
        log.info("第三方支付返回信息:{}", JSON.toJSONString(map));
        return map;
    }
}
